import json

import appium
import selenium
from appium.webdriver import webdriver
# 整个项目工程很多地方都需要获取已经创建好了的驱动对象
from selenium.webdriver.common.by import By


class UtilsDriver:
    # 存储TPshop后台管理系统驱动对象的私有属性
    __admin_driver = None

    # 创建或获取驱动的对象的公用方法
    # 1、创建驱动对象时需要将创建好的窗口存储到私有属性__admin_driver中也就是要修改该变量值而只有类级别的方法才有权限修改
    # 2、如果以实例属性的方式存储浏览器驱动对象,那么在调用方法时就必须创建UtilsDriver的实例对象,每次创建实例对象,其对应的实例
    # 属性都不是同一个,产生的结果还是会打开多个浏览器
    @classmethod
    def get_admin_driver(cls):
        # 如果__admin_driver当前不为空，则代表代码之前已经打开浏览器,那么只需要直接返回已经打开的浏览器驱动对象即可，不需要重新创建
        if cls.__admin_driver is None:
            # 创建驱动对象,因为后续对于该驱动对象需要进行操作,所以需要将创建的好的驱动对象先存储起来
            cls.__admin_driver = selenium.webdriver.Chrome()
            # 窗口最大化
            cls.__admin_driver.maximize_window()
            # 隐式等待
            cls.__admin_driver.implicitly_wait(10)
        # 返回创建好的驱动对象
        return cls.__admin_driver

    # 浏览器开关
    __admin_key = True

    @classmethod
    def change_admin_key(cls, key):
        cls.__admin_key = key

    # 关闭后台管理驱动对象的方法
    @classmethod
    def quit_admin_driver(cls):
        # 为加强代码的健壮,防止在没有创建驱动对象之前直接调用关闭驱动对象的方法导致出错的情况则加上判断是否有打开的浏览器
        if cls.__admin_driver is not None and cls.__admin_key:
            # 1、直接拿到驱动对象之后调用quit()会关闭浏览器窗口,但是不会清除__admin_driver中的缓存值,如果不清楚,则再次调用get_admin_driver就不会
            # 打开浏览器窗口
            cls.__admin_driver.quit()
            # 2、实例方法不能直接修改私有属性所以需要将方法修改为类级别的方法
            cls.__admin_driver = None

    # 存储TPshop门户网站系统驱动对象的私有属性
    __buyer_driver = None

    # 创建或获取驱动的对象的公用方法
    # 1、创建驱动对象时需要将创建好的窗口存储到私有属性__admin_driver中也就是要修改该变量值而只有类级别的方法才有权限修改
    # 2、如果以实例属性的方式存储浏览器驱动对象,那么在调用方法时就必须创建UtilsDriver的实例对象,每次创建实例对象,其对应的实例
    # 属性都不是同一个,产生的结果还是会打开多个浏览器
    # APP
    __app_driver = None

    # 创建或获取驱动的对象的公用方法
    # 1、创建驱动对象时需要将创建好的窗口存储到私有属性__admin_driver中也就是要修改该变量值而只有类级别的方法才有权限修改
    # 2、如果以实例属性的方式存储浏览器驱动对象,那么在调用方法时就必须创建UtilsDriver的实例对象,每次创建实例对象,其对应的实例
    # 属性都不是同一个,产生的结果还是会打开多个浏览器
    @classmethod
    def get__app_driver(cls):
        # 如果__admin_driver当前不为空，则代表代码之前已经打开浏览器,那么只需要直接返回已经打开的浏览器驱动对象即可，不需要重新创建
        if cls.__app_driver is None:
            # 手机端启动参数
            desired_caps = dict()
            # 代表被测试的手机系统型号:IOS 和 Android
            desired_caps['platformName'] = 'Android'
            # 代表被测模拟器/手机系统的版本号,可以写部分版本号，但是不能写错
            desired_caps['platformVersion'] = '5.1'
            # 随便写，但是不能不写
            desired_caps['deviceName'] = '323232'
            # 要启动的应用包名
            desired_caps['appPackage'] = 'com.tencent.news'
            # 要启动的界面名
            desired_caps['appActivity'] = '.activity.SplashActivity'
            # 创建驱动对象
            cls.__app_driver = appium.webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
            # 隐式等待
            cls.__app_driver.implicitly_wait(10)
        # 返回创建好的驱动对象
        return cls.__app_driver

    # 关闭BUYER门户网站驱动对象的方法
    @classmethod
    def quit__app_driver(cls):
        # 为加强代码的健壮,防止在没有创建驱动对象之前直接调用关闭驱动对象的方法导致出错的情况则加上判断是否有打开的浏览器
        if cls.__app_driver is not None:
            # 1、直接拿到驱动对象之后调用quit()会关闭浏览器窗口,但是不会清除__admin_driver中的缓存值,如果不清楚,则再次调用get_admin_driver就不会
            # 打开浏览器窗口
            cls.__app_driver.quit()
            # 2、实例方法不能直接修改私有属性所以需要将方法修改为类级别的方法
            cls.__app_driver = None


def is_el_exits(driver, text):
    xpath_str = '//*[contains(text(),"")]'.format(text)
    try:
        is_suc = driver.find_element(By.XPATH, xpath_str)
    except Exception as e:
        is_suc = False
    return is_suc


def get_build_data(filename):
    case_data = []
    with open(file=filename, encoding='utf8') as f:
        js_data = json.load(f)
        for i in js_data.values():
            a = list(i.values())
            case_data.append(a)
    return case_data
